home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * Copyright © 1991, Apple Computer, Inc.
- *
- * by Rob Glanville
- *
- * 8 May 91
- *
- * JG_kernel.c - A simple kernel for controlling the John Galt Ethernet cards
- * (NOTE: John Galt is some fictional character that nobody cares about)
- *
- */
-
- #pragma On (Constants_in_code)
-
- #define UBYTE unsigned char
- #define UWORD unsigned short
- #define ULONG unsigned long
-
- #define PBYTE *(unsigned char *) /* Used for physical address casting */
- #define PWORD *(unsigned short *) /* Used for physical address casting */
- #define PLONG *(unsigned long *) /* Used for physical address casting */
-
- /* Flag bits */
- #define F_ready 0x80 /* Ready */
- #define F_datachain 0x40 /* DataChain */
- #define F_update 0x20 /* Update */
- #define F_interrupt 0x10 /* Interrupt */
- #define F_timer 0x08 /* TimerInt */
- #define F_aborted 0x04 /* Aborted */
- #define F_overrun 0x02 /* Overrun */
- #define F_size 0x01 /* 0=byte, 1=word */
-
- #define ItFeelsGood 0xfffffff /* Forever flag */
- #define Null 0x0000000
- #define True 0xfffffff
- #define False 0x0000000
- #define Byte 0x00 /* Byte indicator */
- #define Word 0x01 /* Word indicator */
- #define Full 0xff
- #define Empty 0x00
- #define Vectors 0x0000000 /* Start of interrupt vectors */
- #define Command 0x0000400 /* Start of fixed command buffer */
- #define Flags 0x0000401 /* Flags */
- #define Count 0x0000402 /* Count */
- #define Address 0x0000404 /* Address */
- #define TDA 0x0000410 /* Transmit descriptor area */
- #define RDA 0x0000420 /* Receive descriptor area */
- #define RRA 0x0000430 /* Receive descriptor area */
- #define CDA 0x0000440 /* CAM descriptor area */
-
- #define Null 0x00
-
- /************************************* Defines ***********************************************/
-
- #define SONIC 0x00900000
- #define ENetAddress 0x00700000
- #define EnetAdr0 0x00700003 /* This order looks weird but thats the way */
- #define EnetAdr1 0x00700001 /* SONIC likes it */
- #define EnetAdr2 0x00700007
- #define EnetAdr3 0x00700005
- #define EnetAdr4 0x0070000B
- #define EnetAdr5 0x00700009
-
- /************************************* Variables *********************************************/
-
- UWORD TOPOFDATA; /* DO NOT MOVE OR REMOVE!!! This MUST be first to adjust the A5 address register */
-
- UBYTE command;
- UBYTE flags;
- UWORD count;
- ULONG address;
- UBYTE size;
-
- /************************************* Routines **********************************************/
-
- void DoConfiguration() {
- UWORD intStatus;
- ULONG timer;
- PLONG 0x4e4 = 'Conf';
- PWORD 0x900008 = 0x0000; /* Mask all interrupts */
- PWORD 0x90000A = 0x7FFF; /* Clear all interrupts */
- PWORD 0x900000 = 0x0085; /* Reset and stop operations */
- PWORD 0x900002 = 0x0B03; /* Set the configuration register */
- PWORD 0x900000 = 0x0000; /* Remove the reset, stop operations */
- PWORD CDA = 0x0000; /* Set the CAM entry pointer */
- PWORD (CDA + 2) = (PBYTE EnetAdr0 << 8) + (PBYTE EnetAdr1);
- PWORD (CDA + 4) = (PBYTE EnetAdr2 << 8) + (PBYTE EnetAdr3);
- PWORD (CDA + 6) = (PBYTE EnetAdr4 << 8) + (PBYTE EnetAdr5);
- PWORD (CDA + 8) = 0x0001; /* Set the CAM descriptor count */
- PWORD 0x900028 = 0x0000; /* Set upper pointer */
- PWORD 0x90004C = CDA; /* Set lower pointer */
- PWORD 0x90004E = 0x0001; /* Set descriptor count */
- PWORD 0x900000 = 0x0200; /* Set load CAM command */
- timer = 0x10000; /* More than enough time */
- do {
- intStatus = PWORD 0x90000A; /* Read the interrupt status */
- } while (((intStatus & 0x1000) != 0x1000) && (--timer));
- PLONG 0x4e8 = timer;
- }
-
- void DoTransmit() {
- UWORD intStatus;
- ULONG timer;
- PWORD TDA = 0x0000; /* Set status */
- PWORD (TDA + 2) = 0x5000; /* Set configuration */
- PWORD (TDA + 4) = count; /* Set packet length */
- PWORD (TDA + 6) = 0x0001; /* Set fragment count */
- PWORD (TDA + 8) = address; /* Set lower address */
- PWORD (TDA + 10)= 0x0000; /* Set upper address */
- PWORD (TDA + 12)= count; /* Set fragment length */
- PWORD (TDA + 14)= 0x0001; /* Set for no link */
- PWORD 0x90000C = 0x0000; /* Set upper address */
- PWORD 0x90000E = TDA; /* Set Lower address */
- PWORD 0x900000 = 0x0002; /* Start transmission */
- timer = 0x80000; /* More than enough time */
- do {
- intStatus = PWORD 0x90000A; /* Read the interrupt status */
- } while (((intStatus & 0x0200) != 0x0200) && (--timer));
- PWORD 0x90000A = 0x0200; /* Clear the interrupt */
- }
-
- void DoReadStatus() {
- PWORD Count = PWORD 0x90000A;/* Get interrupt status */
- PWORD Address = PWORD 0x900004;/* Get receive status */
- PWORD (Address+2)= PWORD 0x900006;/* Get transmit status */
- }
-
- void DoReceive() {
- UWORD intStatus;
- ULONG timer;
- /* Build the receiver resource area */
- PWORD (RRA ) = address; /* Set lower address */
- PWORD (RRA + 2) = 0x0000; /* Set upper address */
- PWORD (RRA + 4) = count; /* Set lower length */
- PWORD (RRA + 6) = 0x0000; /* Set upper length */
- /* Build receiver descriptor */
- PWORD (RDA ) = 0x0000; /* Set status */
- PWORD (RDA + 2) = 0x0000; /* Set packet length */
- PWORD (RDA + 4) = 0x0000; /* Set lower address */
- PWORD (RDA + 6) = 0x0000; /* Set upper address */
- PWORD (RDA + 8) = 0x0000; /* Set Sequence number */
- PWORD (RDA + 10) = 0x0001; /* Set link */
- PWORD (RDA + 12) = 0xffff; /* Set in use */
- /* Load registers and get read for reception */
- PWORD 0x90001A = 0x0000; /* Set upper address */
- PWORD 0x90001C = RDA; /* Set Lower address */
- PWORD 0x900028 = 0x0000; /* Set upper address */
- PWORD 0x90002A = RRA; /* Set Resource start address */
- PWORD 0x90002C = RRA+4; /* Set Resource end address */
- PWORD 0x90002E = RRA; /* Set Resource read register */
- PWORD 0x900030 = RRA+4; /* Set Resource write register */
- PWORD 0x900056 = 0x0000; /* Set Receive sequence counter */
- PWORD 0x900000 = 0x0100; /* Read RRA */
- PWORD 0x900000 = 0x0008; /* Start receiving */
- timer = 0x800000; /* More than enough time */
- do {
- intStatus = PWORD 0x90000A; /* Read the interrupt status */
- } while (((intStatus & 0x0400) != 0x0400) && (--timer));
- PWORD 0x90000A = 0x0400; /* Clear the interrupt */
- }
-
- void DoCommand() {
- while (((flags = PBYTE Flags) & F_ready) == Null);
- command = PBYTE Command;
- count = PWORD Count;
- address = PLONG Address;
- switch (command) {
- case 0x01 : /* Configure Ethernet */
- DoConfiguration();
- PLONG 0x4d0 = 'Cdon';
- break;
- case 0x02 : /* Transmit packet */
- DoTransmit();
- PLONG 0x4d0 = 'DoTx';
- break;
- case 0x03 : /* Read Status */
- DoReadStatus();
- PLONG 0x4d0 = 'DoSt';
- break;
- case 0x04 : /* Receive packet */
- DoReceive();
- PLONG 0x4d0 = 'DoRx';
- break;
- case 0x81 : /* Read Data */
- if (PBYTE Flags & F_size) size = Word;
- else size = Byte;
- if (size == Word) PWORD Count = PWORD address;
- else PBYTE Count = PBYTE address;
- PLONG 0x4d0 = 'Read';
- break;
- case 0x82 : /* Write data */
- if (PBYTE Flags & F_size) size = Word;
- else size = Byte;
- if (size == Word) PWORD address = count;
- else PBYTE address = count;
- PLONG 0x4d0 = 'Writ';
- break;
- default:
- PLONG 0x4d0 = 'Dflt';
- break;
- }
- PBYTE Flags = (flags & 0x7f); /* Clear ready bit */
- }
-
- void InitializeVectors() {
- /* Initialize the interrupt vectors */
- }
-
- COMMANDLOOP() {
- TOPOFDATA = 'RG'; /* Lets just mark it with something unique */
- InitializeVectors();
- DoConfiguration();
- PBYTE Command = Null; /* Clear the command */
- PBYTE Flags = Null; /* Clear the flags */
- PWORD Count = Null; /* Clear the count */
- PLONG Address = Null; /* Clear the address */
- PLONG 0x4f0 = 'Loop';
- while (ItFeelsGood) {
- DoCommand();
- }
- }